﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "GcmpModelInterface.h"
#include "IElement.h"
#include "NdbDataSchema.h"
#include "GcmpApiDeclaration.h"


namespace gcmp
{
    /// \brief CoordinateSystemAxis 表示坐标轴类型
    SERIALIZABLE_ENUM_CLASS(CoordinateSystemAxis)
    {
        X = 0, ///< X轴。
        Y = 1, ///< Y轴。
        Z = 2, ///< Z轴。
        NONE   ///< 无类型
    };

    class IElementLocatorPositionChangeEventHandler;
    class IElementLocatorMoveAndRotateEventHandler;
    class Coordinate3d;

    /// \brief 罗盘接口。用户可以通过该接口的静态Get()方法获取到罗盘对象指针。
    class GCMP_MODEL_INTERFACE_EXPORT IElementLocator : public IElement
    {
        DEFINE_CAST_DERIVED(gcmp::IElementLocator, gcmp::IElement);

    public:
        /// \brief 获取罗盘对象指针。
        /// \param pDocument 文档对象指针。
        /// \return 返回罗盘对象指针。
        static IElementLocator* Get(const IDocument* pDocument);

        /// \brief 设置坐标系。
        /// \param value 需要设置的坐标系。
        /// \return 返回true表示设置成功；返回false表示设置失败。
        virtual bool SetCoordinateSystem(const Coordinate3d& value) = 0;
        
        /// \brief 获取坐标系。
        /// 
        /// \return 返回坐标系引用。
        virtual const Coordinate3d& GetCoordinateSystem() const = 0;

        /// \brief 判断是否允许平移XY平面。
        /// 
        /// \return 返回true表示允许平移XY平面；返回false表示不允许平移XY平面。
        virtual bool IsAllowMovePlanarXY() const = 0;
        
        /// \brief 判断是否允许平移XZ平面。
        /// 
        /// \return 返回true表示允许平移XZ平面；返回false表示不允许平移XZ平面。
        virtual bool IsAllowMovePlanarXZ() const = 0;

        /// \brief 判断是否允许平移YZ平面。
        /// 
        /// \return 返回true表示允许平移YZ平面；返回false表示不允许平移YZ平面。
        virtual bool IsAllowMovePlanarYZ() const = 0;

        /// \brief 判断是否允许平移X轴
        /// 
        /// \return 返回true表示允许平移X轴；返回false表示不允许平移X轴
        virtual bool IsEnableMovementX() const = 0;

        /// \brief 判断是否允许显示平移轴X
        /// 
        /// \return 返回true表示允许显示；返回false表示不允许显示
        virtual bool IsShowMovementX() const = 0;

        /// \brief 判断是否允许平移Y轴
        /// 
        /// \return 返回true表示允许平移Y轴；返回false表示不允许平移Y轴
        virtual bool IsEnableMovementY() const = 0;

        /// \brief 判断是否允许显示平移轴Y
        /// 
        /// \return 返回true表示允许显示；返回false表示不允许显示
        virtual bool IsShowMovementY() const = 0;

        /// \brief 判断是否允许平移Z轴
        /// 
        /// \return 返回true表示允许平移Z轴；返回false表示不允许平移Z轴
        virtual bool IsEnableMovementZ() const = 0;

        /// \brief 判断是否允许显示平移轴Z
        /// 
        /// \return 返回true表示允许显示；返回false表示不允许显示
        virtual bool IsShowMovementZ() const = 0;

        /// \brief 判断是否允许绕X轴旋转
        /// 
        /// \return 返回true表示允许绕X轴旋转；返回false表示不允许绕X轴旋转
        virtual bool IsEnableRotationX() const = 0;

        /// \brief 判断是否允许显示旋转轴X
        /// 
        /// \return 返回true表示允许显示；返回false表示不允许显示
        virtual bool IsShowRotationX() const = 0;

        /// \brief 判断是否允许绕Y轴旋转
        /// 
        /// \return 返回true表示允许绕Y轴旋转；返回false表示不允许绕Y轴旋转
        virtual bool IsEnableRotationY() const = 0;

        /// \brief 判断是否允许显示旋转轴Y
        /// 
        /// \return 返回true表示允许显示；返回false表示不允许显示
        virtual bool IsShowRotationY() const = 0;

        /// \brief 判断是否允许绕Z轴旋转
        /// 
        /// \return 返回true表示允许绕Z轴旋转；返回false表示不允许绕Z轴旋转
        virtual bool IsEnableRotationZ() const = 0;

        /// \brief 判断是否允许显示旋转轴Z
        /// 
        /// \return 返回true表示允许显示；返回false表示不允许显示
        virtual bool IsShowRotationZ() const = 0;

        /// \brief 使能所有的平移和旋转
        /// 
        /// \return 返回true表示使能成功；返回false表示使能失败
        virtual bool EnableAndShowAllMovementAndRotation() = 0;

        /// \brief 禁用所有的平移和旋转
        /// 
        /// \return 返回true表示禁用成功；返回false表示禁用失败
        virtual bool DisableAllMovementAndRotation() = 0;

        /// \brief 隐藏所有的平移和旋转
        /// 
        /// \return 返回true表示隐藏成功；返回false表示隐藏失败
        virtual bool HideAllMovementAndRotation() = 0;

        /// \brief 禁用平移X轴
        /// 
        /// \return 返回true表示禁用成功；返回false表示禁用失败
        virtual bool DisableMovementX() = 0;

        /// \brief 隐藏平移轴X
        /// 
        /// \return 返回true表示隐藏成功；返回false表示隐藏失败
        virtual bool HideMovementX() = 0;

        /// \brief 禁用平移Y轴
        /// 
        /// \return 返回true表示禁用成功；返回false表示禁用失败
        virtual bool DisableMovementY() = 0;

        /// \brief 隐藏平移轴Y
        /// 
        /// \return 返回true表示隐藏成功；返回false表示隐藏失败
        virtual bool HideMovementY() = 0;

        /// \brief 禁用平移Z轴
        /// 
        /// \return 返回true表示禁用成功；返回false表示禁用失败
        virtual bool DisableMovementZ() = 0;

        /// \brief 隐藏平移轴Z
        /// 
        /// \return 返回true表示隐藏成功；返回false表示隐藏失败
        virtual bool HideMovementZ() = 0;

        /// \brief 禁用绕X轴旋转
        /// 
        /// \return 返回true表示禁用成功；返回false表示禁用失败
        virtual bool DisableRotationX() = 0;

        /// \brief 隐藏旋转轴X
        /// 
        /// \return 返回true表示隐藏成功；返回false表示隐藏失败
        virtual bool HideRotationX() = 0;

        /// \brief 禁用绕Y轴旋转
        /// 
        /// \return 返回true表示禁用成功；返回false表示禁用失败
        virtual bool DisableRotationY() = 0;

        /// \brief 隐藏旋转轴Y
        /// 
        /// \return 返回true表示隐藏成功；返回false表示隐藏失败
        virtual bool HideRotationY() = 0;

        /// \brief 禁用绕Z轴旋转
        /// 
        /// \return 返回true表示禁用成功；返回false表示禁用失败
        virtual bool DisableRotationZ() = 0;

        /// \brief 隐藏旋转轴Z
        /// 
        /// \return 返回true表示隐藏成功；返回false表示隐藏失败
        virtual bool HideRotationZ() = 0;

        /// \brief 设置选择的元素ID集。
        /// \param ids 选择的元素ID集引用。
        /// \return 返回true表示设置成功；返回false表示设置失败。
        virtual bool SetSelectedElementIds(const std::set<ElementId> &ids) = 0;
        
        /// \brief 获取选择的元素ID集。
        /// 
        /// \return 选择的元素ID集引用。
        virtual const std::set<ElementId>& GetSelectedElementIds() const = 0;

        /// \brief 注册罗盘位置改变事件的处理者。
        /// \param pHandler 罗盘位置改变事件的处理者。
        /// \return 返回true表示注册成功；返回false表示注册失败。
        virtual bool RegisterElementLocatorPositionChangeEventHandler(IElementLocatorPositionChangeEventHandler* pHandler) = 0;

        /// \brief 取消注册罗盘位置改变事件的处理者。
        /// \param pHandler 罗盘位置改变事件的处理者。
        /// \return 返回true表示取消注册成功，否则返回false。
        virtual bool UnregisterElementLocatorPositionChangeEventHandler(IElementLocatorPositionChangeEventHandler* pHandler) = 0;
        
        /// \brief 注册罗盘平移和旋转事件的处理者。
        /// \param pHandler 罗盘平移和旋转事件的处理者。
        /// \return 返回true表示注册成功；返回false表示注册失败。
        virtual bool RegisterElementLocatorMoveAndRotateEventHandler(IElementLocatorMoveAndRotateEventHandler* pHandler) = 0;

        /// \brief 取消注册罗盘平移和旋转事件的处理者。
        /// \param pHandler 罗盘平移和旋转事件的处理者。
        /// \return 返回true表示取消注册成功，否则返回false。
        virtual bool UnregisterElementLocatorMoveAndRotateEventHandler(IElementLocatorMoveAndRotateEventHandler* pHandler) = 0;

        /// \brief 获取移动轴的坐标轴类型（X轴、Y轴还是Z轴）
        /// \param pElement 当前对象元素
        /// \return 移动轴的坐标轴类型
        virtual CoordinateSystemAxis GetMovementAxis(const IElement* pElement) const = 0;

    public:
        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();
        
    };
}
